// Copyright (c) 2020-present,  INSPUR Co, Ltd.  All rights reserved.
// This source code is licensed under Apache 2.0 License.

#include "pure_mem/memoryblock/memory_arena_index/memory_arena_art_index.h"

namespace rocksdb{
    MemArenaARTIndex::MemArenaARTIndex(const InternalKeyComparator& mkeyCmp)
    : MemArenaIndex(mkeyCmp), mkey_cmp_(mkeyCmp){
    }

    bool MemArenaARTIndex::Insert(const Slice &startKey, IMemoryArena *memoryArena) {
      ////相同userkey更新memoryArena怎么处理?
      //userkey相同，修改versionnode内的MemoryArena

      uint32_t len = startKey.size() + 8 + 1;
      uint32_t key_size = VarintLength(len) + len;
      uint32_t val_size = 8;
      const uint32_t encoded_len = key_size + val_size;
      // key + value(8-bit pointer)
      // handle keycompare
      char* buf = new char[encoded_len];
      memset(buf, '\0', key_size);
      memset(buf + key_size - 8, 255, 8);
      char* p = EncodeVarint32(buf, len);
      memcpy(p, startKey.data(), startKey.size());
      p += len;
      memcpy(p, &memoryArena, val_size);

      ////多线程时-------------??
      auto iter = art_list_.GetIterator();
      Slice seek_key = Slice(buf + VarintLength(len), len);
      iter->Seek(seek_key);
      //iter->Valid()说明第一层ART索引中已经存在当前startkey
      if(iter->Valid()){
        Slice handle = GetLengthPrefixedSlice(iter->key());
        auto val_addr = handle.data() + handle.size();
        memcpy((void *) val_addr, &memoryArena, val_size);
        //std::cout<<"userkey : "<<startKey.ToString()<<"相同, memoryarena : "<<memoryArena<<std::endl;
        return true;
      }

      auto node = new VersionNode();
      node->SetNext(nullptr);
      node->SetPrev(nullptr);
      bool res = node->CASSetKey(nullptr, buf);
      assert(res);

      // write the assembled key into the art
      bool ok = art_list_.Insert(reinterpret_cast<const char *>(node));
      return ok;
    }

    //key为internal_key
    IMemoryArena *MemArenaARTIndex::SeekForMemoryArena(const Slice& key) {
      auto iter = art_list_.GetIterator();
      iter->HashSeekForPrevOrEqual(key);
      if (!iter->Valid()) {
        std::cout << "没有找到对应的MemoryArena！！" << std::endl;
        return nullptr;
      }

      Slice handle = GetLengthPrefixedSlice(iter->key());
      const char* val_addr = handle.data() + handle.size();
      IMemoryArena* addr = *(IMemoryArena * *)(val_addr);
      return addr;

    }

    void MemArenaARTIndex::ClearMemoryArena() {
      auto iter = this->art_list_.GetIterator();
      iter->SeekToFirst();
      while (iter->Valid()){
        delete[] iter->key();
        iter->Next();
      }
    }

    MemArenaARTIndex::~MemArenaARTIndex() {
      this->ClearMemoryArena();
    }


}  //namespace rocksdb